/*-------------------------------------------------------------------------
 *
 * var.c
 *	  Var 节点操作例程
 *
 * 注意：在大多数情况下，PlaceHolderVar 也被视为 Var，
 * 即使其包含的表达式没有变量。此外，CurrentOfExpr
 * 在确定表达式是否包含变量时被视为 Var。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/optimizer/util/var.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "access/sysattr.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "optimizer/placeholder.h"
#include "optimizer/prep.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteManip.h"


typedef struct
{
	Relids		varnos;
	PlannerInfo *root;
	int			sublevels_up;
} pull_varnos_context;

typedef struct
{
	Bitmapset  *varattnos;
	Index		varno;
} pull_varattnos_context;

typedef struct
{
	List	   *vars;
	int			sublevels_up;
} pull_vars_context;

typedef struct
{
	int			var_location;
	int			sublevels_up;
} locate_var_of_level_context;

typedef struct
{
	List	   *varlist;
	int			flags;
} pull_var_clause_context;

typedef struct
{
	Query	   *query;			/* 外部查询 */
	int			sublevels_up;
	bool		possible_sublink;	/* 别名中可能包括 SubLink 吗？ */
	bool		inserted_sublink;	/* 我们插入了一个 SubLink 吗？ */
} flatten_join_alias_vars_context;

static bool fc_pull_varnos_walker(Node *fc_node,
							   pull_varnos_context *fc_context);
static bool fc_pull_varattnos_walker(Node *fc_node, pull_varattnos_context *fc_context);
static bool fc_pull_vars_walker(Node *fc_node, pull_vars_context *fc_context);
static bool fc_contain_var_clause_walker(Node *fc_node, void *fc_context);
static bool fc_contain_vars_of_level_walker(Node *fc_node, int *fc_sublevels_up);
static bool fc_locate_var_of_level_walker(Node *fc_node,
									   locate_var_of_level_context *fc_context);
static bool fc_pull_var_clause_walker(Node *fc_node,
								   pull_var_clause_context *fc_context);
static Node *fc_flatten_join_alias_vars_mutator(Node *fc_node,
											 flatten_join_alias_vars_context *fc_context);
static Relids fc_alias_relid_set(Query *fc_query, Relids fc_relids);


/*
 * pull_varnos
 *		创建一组在解析树中存在的所有不同 varnos。
 *		仅考虑引用零级 rtable 条目的 varnos。
 *
 * 如果不需要处理 PlaceHolderVars，"root" 可以传递为 NULL。
 *
 * 注意：这用于尚未计划的表达式。因此，它可能会找到裸 SubLinks，如果是这样，它需要递归进入它们以查找对所需 rtable 级别的上级引用！但当我们找到一个已经完成的 SubPlan 时，我们只需要查看传递给子计划的参数。
 */
Relids pull_varnos(PlannerInfo *fc_root, Node *fc_node)
{
	pull_varnos_context fc_context;

	fc_context.varnos = NULL;
	fc_context.root = fc_root;
	fc_context.sublevels_up = 0;

	/*
	 * 必须准备从查询或裸表达式树开始；如果是查询，我们不想增加 sublevels_up。
	 */
	query_or_expression_tree_walker(fc_node,
									fc_pull_varnos_walker,
									(void *) &fc_context,
									0);

	return fc_context.varnos;
}

/*
 * pull_varnos_of_level
 *		创建一组在解析树中存在的所有不同 varnos。
 *		仅考虑指定级别的 Vars。
 */
Relids pull_varnos_of_level(PlannerInfo *fc_root, Node *fc_node, int fc_levelsup)
{
	pull_varnos_context fc_context;

	fc_context.varnos = NULL;
	fc_context.root = fc_root;
	fc_context.sublevels_up = fc_levelsup;

	/*
	 * 必须准备从查询或裸表达式树开始；如果是查询，我们不想增加 sublevels_up。
	 */
	query_or_expression_tree_walker(fc_node,
									fc_pull_varnos_walker,
									(void *) &fc_context,
									0);

	return fc_context.varnos;
}

static bool fc_pull_varnos_walker(Node *fc_node, pull_varnos_context *fc_context)
{
	if (fc_node == NULL)
		return false;
	if (IsA(fc_node, Var))
	{
		Var		   *fc_var = (Var *) fc_node;

		if (fc_var->varlevelsup == fc_context->sublevels_up)
			fc_context->varnos = bms_add_member(fc_context->varnos, fc_var->varno);
		return false;
	}
	if (IsA(fc_node, CurrentOfExpr))
	{
		CurrentOfExpr *fc_cexpr = (CurrentOfExpr *) fc_node;

		if (fc_context->sublevels_up == 0)
			fc_context->varnos = bms_add_member(fc_context->varnos, fc_cexpr->cvarno);
		return false;
	}
	if (IsA(fc_node, PlaceHolderVar))
	{
		PlaceHolderVar *fc_phv = (PlaceHolderVar *) fc_node;

		/*
		 * 如果 PlaceHolderVar 不是目标查询级别，则忽略它，而是递归进入其表达式，以查看它是否包含任何目标级别的变量。当调用者未传递 "root" 指针时，我们也会这样做。（在这种情况下，我们可能根本不应该看到 PlaceHolderVars，但如果我们看到了，这是一个合理的行为。）
		 */
		if (fc_phv->phlevelsup == fc_context->sublevels_up &&
			fc_context->root != NULL)
		{
			
/*
			 * 理想情况下，PHV 对 context->varnos 的贡献是其
			 * ph_eval_at 集合。然而，这段代码可能会在
			 * 计算之前被调用。如果我们找不到 PlaceHolderInfo，
			 * 那么保守的假设是 PHV 将在其句法级别（phv->phrels）进行评估。
			 *
			 * 还有第二个风险：这段代码也用于检查
			 * qual 子句在 deconstruct_jointree 期间，当我们可能有一个
			 * PlaceHolderInfo 但它的 ph_eval_at 值尚未确定时，
			 * 理论上我们可能会得到一个 relid 集，这个集合可能小于
			 * 后面看到的。然而，这种情况永远不会发生，因为我们
			 * 是从上往下构建 jointree。任何强制推迟给定
			 * qual 子句评估的外连接将在我们在这里检查该子句之前处理，
			 * 因此 ph_eval_at 值应该已经更新以包含它。
			 *
			 * 另一个问题是 PlaceHolderVar 可能出现在
			 * 为子 appendrel 使用而翻译的 quals 或
			 * tlists 中。通常此类 PHV 是由其他关系源的参数表达式，
			 * 因此从父 appendrel 到子 appendrel 的翻译不会更改其
			 * phrels，我们仍然应该将 ph_eval_at 视为有效。
			 * 但在特定情况下，PHV 的原始 phrels 可能包含父
			 * appendrel 本身，在这种情况下，翻译后的 PHV 将在
			 * phrels 中包含子 appendrel，我们必须将 ph_eval_at
			 * 转换以匹配。
			 */
			PlaceHolderInfo *fc_phinfo = NULL;

			if (fc_phv->phlevelsup == 0)
			{
				ListCell   *fc_lc;

				foreach(fc_lc, fc_context->root->placeholder_list)
				{
					fc_phinfo = (PlaceHolderInfo *) lfirst(fc_lc);
					if (fc_phinfo->phid == fc_phv->phid)
						break;
					fc_phinfo = NULL;
				}
			}
			if (fc_phinfo == NULL)
			{
				/* 尚未找到 PlaceHolderInfo，使用 phrels */
				fc_context->varnos = bms_add_members(fc_context->varnos,
												  fc_phv->phrels);
			}
			else if (bms_equal(fc_phv->phrels, fc_phinfo->ph_var->phrels))
			{
				/* 正常情况：使用 ph_eval_at */
				fc_context->varnos = bms_add_members(fc_context->varnos,
												  fc_phinfo->ph_eval_at);
			}
			else
			{
				/* Translated PlaceHolderVar: translate ph_eval_at to match */
				Relids		fc_newevalat,
							fc_delta;

				/* 从 phv->phrels 中移除被移除的内容... */
				fc_delta = bms_difference(fc_phinfo->ph_var->phrels, fc_phv->phrels);
				fc_newevalat = bms_difference(fc_phinfo->ph_eval_at, fc_delta);
				/* ...那么如果那实际上是 ph_eval_at 的一部分... */
				if (!bms_equal(fc_newevalat, fc_phinfo->ph_eval_at))
				{
					/* ...添加被添加的内容 */
					fc_delta = bms_difference(fc_phv->phrels, fc_phinfo->ph_var->phrels);
					fc_newevalat = bms_join(fc_newevalat, fc_delta);
				}
				fc_context->varnos = bms_join(fc_context->varnos,
										   fc_newevalat);
			}
			return false;		/* 不要递归进入表达式 */
		}
	}
	else if (IsA(fc_node, Query))
	{
		/* 递归进入RTE子查询或尚未规划的子链接子查询 */
		bool		fc_result;

		fc_context->sublevels_up++;
		fc_result = query_tree_walker((Query *) fc_node, fc_pull_varnos_walker,
								   (void *) fc_context, 0);
		fc_context->sublevels_up--;
		return fc_result;
	}
	return expression_tree_walker(fc_node, fc_pull_varnos_walker,
								  (void *) fc_context);
}


/*
 * pull_varattnos
 *		查找表达式树中所有不同的属性编号，
 *		并将它们添加到 *varattnos 的初始内容中。
 *		只考虑给定 varno 和 rtable 级别为零的 Vars。
 *
 * 属性编号通过 FirstLowInvalidHeapAttributeNumber 偏移，
 * 以便我们可以在位图表示中包含系统属性（例如，OID）。
 *
 * 目前，这不支持未计划的子查询；这在当前使用中并不需要。
 * 不过，它会处理已经计划的 SubPlan 节点，
 * 仅考察 "testexpr" 和 "args" 列表。 （子计划无法
 * 包含对当前级别 Vars 的任何其他引用。）
 */
void pull_varattnos(Node *fc_node, Index fc_varno, Bitmapset **fc_varattnos)
{
	pull_varattnos_context fc_context;

	fc_context.varattnos = *fc_varattnos;
	fc_context.varno = fc_varno;

	(void) fc_pull_varattnos_walker(fc_node, &fc_context);

	*fc_varattnos = fc_context.varattnos;
}

static bool fc_pull_varattnos_walker(Node *fc_node, pull_varattnos_context *fc_context)
{
	if (fc_node == NULL)
		return false;
	if (IsA(fc_node, Var))
	{
		Var		   *fc_var = (Var *) fc_node;

		if (fc_var->varno == fc_context->varno && fc_var->varlevelsup == 0)
			fc_context->varattnos =
				bms_add_member(fc_context->varattnos,
							   fc_var->varattno - FirstLowInvalidHeapAttributeNumber);
		return false;
	}

	/* 不应该找到未计划的子查询 */
	Assert(!IsA(fc_node, Query));

	return expression_tree_walker(fc_node, fc_pull_varattnos_walker,
								  (void *) fc_context);
}


/*
 * pull_vars_of_level
 *		创建一个列表，包含所有引用指定查询级别的 Vars（和 PlaceHolderVars）
 *		在给定的 parsetree 中。
 *
 * 注意：这些 Vars 并不是被复制的，仅仅被链接到列表中。
 */
List * pull_vars_of_level(Node *fc_node, int fc_levelsup)
{
	pull_vars_context fc_context;

	fc_context.vars = NIL;
	fc_context.sublevels_up = fc_levelsup;

	/*
	 * 必须准备从查询或裸表达式树开始；如果是查询，我们不想增加 sublevels_up。
	 */
	query_or_expression_tree_walker(fc_node,
									fc_pull_vars_walker,
									(void *) &fc_context,
									0);

	return fc_context.vars;
}

static bool fc_pull_vars_walker(Node *fc_node, pull_vars_context *fc_context)
{
	if (fc_node == NULL)
		return false;
	if (IsA(fc_node, Var))
	{
		Var		   *fc_var = (Var *) fc_node;

		if (fc_var->varlevelsup == fc_context->sublevels_up)
			fc_context->vars = lappend(fc_context->vars, fc_var);
		return false;
	}
	if (IsA(fc_node, PlaceHolderVar))
	{
		PlaceHolderVar *fc_phv = (PlaceHolderVar *) fc_node;

		if (fc_phv->phlevelsup == fc_context->sublevels_up)
			fc_context->vars = lappend(fc_context->vars, fc_phv);
		/* 我们不想查看包含的表达式 */
		return false;
	}
	if (IsA(fc_node, Query))
	{
		/* 递归进入RTE子查询或尚未规划的子链接子查询 */
		bool		fc_result;

		fc_context->sublevels_up++;
		fc_result = query_tree_walker((Query *) fc_node, fc_pull_vars_walker,
								   (void *) fc_context, 0);
		fc_context->sublevels_up--;
		return fc_result;
	}
	return expression_tree_walker(fc_node, fc_pull_vars_walker,
								  (void *) fc_context);
}


/*
 * contain_var_clause
 *	  递归扫描一个子句以发现它是否包含任何 Var 节点
 *	  （当前查询级别的）。
 *
 *	  如果找到任何 varnode，则返回 true。
 *
 * 不检查子查询，因此必须仅在将子链接简化为子计划之后使用！
 */
bool contain_var_clause(Node *fc_node)
{
	return fc_contain_var_clause_walker(fc_node, NULL);
}

static bool fc_contain_var_clause_walker(Node *fc_node, void *fc_context)
{
	if (fc_node == NULL)
		return false;
	if (IsA(fc_node, Var))
	{
		if (((Var *) fc_node)->varlevelsup == 0)
			return true;		/* 中止树遍历并返回 true */
		return false;
	}
	if (IsA(fc_node, CurrentOfExpr))
		return true;
	if (IsA(fc_node, PlaceHolderVar))
	{
		if (((PlaceHolderVar *) fc_node)->phlevelsup == 0)
			return true;		/* 中止树遍历并返回 true */
		/* 否则继续检查包含的表达式 */
	}
	return expression_tree_walker(fc_node, fc_contain_var_clause_walker, fc_context);
}


/*
 * contain_vars_of_level
 *	  递归扫描一个子句以发现它是否包含任何指定查询级别的 Var 节点。
 *
 *	  如果找到任何这样的 Var，则返回 true。
 *
 * 会递归进入子链接。同时，也可以直接在查询上调用。
 */
bool contain_vars_of_level(Node *fc_node, int fc_levelsup)
{
	int			fc_sublevels_up = fc_levelsup;

	return query_or_expression_tree_walker(fc_node,
										   fc_contain_vars_of_level_walker,
										   (void *) &fc_sublevels_up,
										   0);
}

static bool fc_contain_vars_of_level_walker(Node *fc_node, int *fc_sublevels_up)
{
	if (fc_node == NULL)
		return false;
	if (IsA(fc_node, Var))
	{
		if (((Var *) fc_node)->varlevelsup == *fc_sublevels_up)
			return true;		/* 中止树遍历并返回 true */
		return false;
	}
	if (IsA(fc_node, CurrentOfExpr))
	{
		if (*fc_sublevels_up == 0)
			return true;
		return false;
	}
	if (IsA(fc_node, PlaceHolderVar))
	{
		if (((PlaceHolderVar *) fc_node)->phlevelsup == *fc_sublevels_up)
			return true;		/* 中止树遍历并返回 true */
		/* 否则继续检查包含的表达式 */
	}
	if (IsA(fc_node, Query))
	{
		/* 递归进入子选择 */
		bool		fc_result;

		(*fc_sublevels_up)++;
		fc_result = query_tree_walker((Query *) fc_node,
								   fc_contain_vars_of_level_walker,
								   (void *) fc_sublevels_up,
								   0);
		(*fc_sublevels_up)--;
		return fc_result;
	}
	return expression_tree_walker(fc_node,
								  fc_contain_vars_of_level_walker,
								  (void *) fc_sublevels_up);
}


/*
 * locate_var_of_level
 *	  查找指定查询级别的任何 Var 的解析位置。
 *
 * 如果查询树中没有这样的 Var，或者它们都具有
 * 未知的解析位置，则返回 -1。 （前一种情况可能是调用者错误，
 * 但我们不费心将其与后一种情况区分开。）
 *
 * 会递归进入子链接。同时，也可以直接在查询上调用。
 *
 * 注意：将该功能合并到 contain_vars_of_level 似乎是合适的，
 * 但这会使该功能的 API 变得复杂。
 * 目前，该功能的唯一用途是用于错误报告，
 * 因此节省周期可能并不是非常重要。
 */
int locate_var_of_level(Node *fc_node, int fc_levelsup)
{
	locate_var_of_level_context fc_context;

	fc_context.var_location = -1;	/* 如果我们什么都没找到 */
	fc_context.sublevels_up = fc_levelsup;

	(void) query_or_expression_tree_walker(fc_node,
										   fc_locate_var_of_level_walker,
										   (void *) &fc_context,
										   0);

	return fc_context.var_location;
}

static bool fc_locate_var_of_level_walker(Node *fc_node,
						   locate_var_of_level_context *fc_context)
{
	if (fc_node == NULL)
		return false;
	if (IsA(fc_node, Var))
	{
		Var		   *fc_var = (Var *) fc_node;

		if (fc_var->varlevelsup == fc_context->sublevels_up &&
			fc_var->location >= 0)
		{
			fc_context->var_location = fc_var->location;
			return true;		/* 中止树遍历并返回 true */
		}
		return false;
	}
	if (IsA(fc_node, CurrentOfExpr))
	{
		/* 由于 CurrentOfExpr 不携带位置，我们无能为力 */
		return false;
	}
	/* 不需要额外的代码来处理 PlaceHolderVar；只需查看包含的表达式 */
	if (IsA(fc_node, Query))
	{
		/* 递归进入子选择 */
		bool		fc_result;

		fc_context->sublevels_up++;
		fc_result = query_tree_walker((Query *) fc_node,
								   fc_locate_var_of_level_walker,
								   (void *) fc_context,
								   0);
		fc_context->sublevels_up--;
		return fc_result;
	}
	return expression_tree_walker(fc_node,
								  fc_locate_var_of_level_walker,
								  (void *) fc_context);
}



/*
 * pull_var_clause
 *	  递归地从表达式子句中提取所有的 Var 节点。
 *
 *	  Aggrefs 根据 'flags' 中这些位进行处理：
 *		PVC_INCLUDE_AGGREGATES		在输出列表中包括 Aggrefs
 *		PVC_RECURSE_AGGREGATES		递归进入 Aggref 参数
 *		两个标志都不设置			发现 Aggref 时抛出错误
 *	  只有在指定 PVC_RECURSE_AGGREGATES 时，Aggref 表达式中的 Vars 才会被包含在结果中。
 *
 *	  WindowFuncs 根据 'flags' 中这些位进行处理：
 *		PVC_INCLUDE_WINDOWFUNCS	在输出列表中包括 WindowFuncs
 *		PVC_RECURSE_WINDOWFUNCS	递归进入 WindowFunc 参数
 *		两个标志都不设置			发现 WindowFunc 时抛出错误
 *	  只有在指定 PVC_RECURSE_WINDOWFUNCS 时，WindowFunc 表达式中的 Vars 才会被包含在结果中。
 *
 *	  PlaceHolderVars 根据 'flags' 中这些位进行处理：
 *		PVC_INCLUDE_PLACEHOLDERS	在输出列表中包括 PlaceHolderVars
 *		PVC_RECURSE_PLACEHOLDERS	递归进入 PlaceHolderVar 参数
 *		两个标志都不设置			发现 PlaceHolderVar 时抛出错误
 *	  只有在指定 PVC_RECURSE_PLACEHOLDERS 时，PHV 表达式中的 Vars 才会被包含在结果中。
 *
 *	  GroupingFuncs 的处理与 Aggrefs 完全相同，因此不需要它们自己的标志位。
 *
 *	  在所有情况下忽略 CurrentOfExpr 节点。
 *
 *	  不应在此看到上级 Vars（varlevelsup > 0），同样上级 Aggrefs 和 PlaceHolderVars 也不应出现。
 *
 *	  返回找到的节点列表。请注意，节点本身没有被复制，仅被引用。
 *
 * 不检查子查询，因此必须在将子链接减少到子计划后才能使用！
 */
List * pull_var_clause(Node *fc_node, int fc_flags)
{
	pull_var_clause_context fc_context;

	/* 确保调用者没有指定不一致的标志 */
	Assert((fc_flags & (PVC_INCLUDE_AGGREGATES | PVC_RECURSE_AGGREGATES))
		   != (PVC_INCLUDE_AGGREGATES | PVC_RECURSE_AGGREGATES));
	Assert((fc_flags & (PVC_INCLUDE_WINDOWFUNCS | PVC_RECURSE_WINDOWFUNCS))
		   != (PVC_INCLUDE_WINDOWFUNCS | PVC_RECURSE_WINDOWFUNCS));
	Assert((fc_flags & (PVC_INCLUDE_PLACEHOLDERS | PVC_RECURSE_PLACEHOLDERS))
		   != (PVC_INCLUDE_PLACEHOLDERS | PVC_RECURSE_PLACEHOLDERS));

	fc_context.varlist = NIL;
	fc_context.flags = fc_flags;

	fc_pull_var_clause_walker(fc_node, &fc_context);
	return fc_context.varlist;
}

static bool fc_pull_var_clause_walker(Node *fc_node, pull_var_clause_context *fc_context)
{
	if (fc_node == NULL)
		return false;
	if (IsA(fc_node, Var))
	{
		if (((Var *) fc_node)->varlevelsup != 0)
			elog(ERROR, "Upper-level Var found where not expected");
		fc_context->varlist = lappend(fc_context->varlist, fc_node);
		return false;
	}
	else if (IsA(fc_node, Aggref))
	{
		if (((Aggref *) fc_node)->agglevelsup != 0)
			elog(ERROR, "Upper-level Aggref found where not expected");
		if (fc_context->flags & PVC_INCLUDE_AGGREGATES)
		{
			fc_context->varlist = lappend(fc_context->varlist, fc_node);
			/* 我们不向下深入包含的表达式 */
			return false;
		}
		else if (fc_context->flags & PVC_RECURSE_AGGREGATES)
		{
			/* 继续递归到聚合的参数 */
		}
		else
			elog(ERROR, "Aggref found where not expected");
	}
	else if (IsA(fc_node, GroupingFunc))
	{
		if (((GroupingFunc *) fc_node)->agglevelsup != 0)
			elog(ERROR, "Upper-level GROUPING found where not expected");
		if (fc_context->flags & PVC_INCLUDE_AGGREGATES)
		{
			fc_context->varlist = lappend(fc_context->varlist, fc_node);
			/* 我们不向下深入包含的表达式 */
			return false;
		}
		else if (fc_context->flags & PVC_RECURSE_AGGREGATES)
		{
			/* 继续递归到 GroupingFunc 的参数 */
		}
		else
			elog(ERROR, "GROUPING found where not expected");
	}
	else if (IsA(fc_node, WindowFunc))
	{
		/* WindowFuncs 没有 levelsup 字段可以检查... */
		if (fc_context->flags & PVC_INCLUDE_WINDOWFUNCS)
		{
			fc_context->varlist = lappend(fc_context->varlist, fc_node);
			/* 我们不向下深入包含的表达式 */
			return false;
		}
		else if (fc_context->flags & PVC_RECURSE_WINDOWFUNCS)
		{
			/* 继续递归到 windowfunc 的参数 */
		}
		else
			elog(ERROR, "WindowFunc found where not expected");
	}
	else if (IsA(fc_node, PlaceHolderVar))
	{
		if (((PlaceHolderVar *) fc_node)->phlevelsup != 0)
			elog(ERROR, "Upper-level PlaceHolderVar found where not expected");
		if (fc_context->flags & PVC_INCLUDE_PLACEHOLDERS)
		{
			fc_context->varlist = lappend(fc_context->varlist, fc_node);
			/* 我们不向下深入包含的表达式 */
			return false;
		}
		else if (fc_context->flags & PVC_RECURSE_PLACEHOLDERS)
		{
			/* 继续递归到占位符的表达式 */
		}
		else
			elog(ERROR, "PlaceHolderVar found where not expected");
	}
	return expression_tree_walker(fc_node, fc_pull_var_clause_walker,
								  (void *) fc_context);
}


/*
 * flatten_join_alias_vars
 *	  用对原始关系变量的引用替换引用 JOIN 输出的 Vars。
 *	  这允许涉及这些 vars 的条件被向下推动。引用 JOIN 关系的整个行 Vars
 *	  被展开成列出单个输出 Vars 的 RowExpr 结构。这是必要的，因为我们不会将
 *	  JOIN 视为基础关系，这是执行器可以直接处理整个行 Vars 的唯一方式。
 *
 * 这也调整在某些表达式节点类型中找到的 relid 集，以便用包含的基础 rels
 * 替换任何连接 relid。
 *
 * 如果一个 JOIN 包含已经被展平的子选择，那么它的连接别名项现在可能是任意的表达式，而不仅仅是 Vars。
 * 这在一个重要的方面影响这个函数：我们可能会发现自己在子查询中插入 SubLink 表达式，
 * 并且我们必须确保它们的 Query.hasSubLinks 字段在这种情况下被设置为 true。
 * 如果连接别名列表中有任何 SubLinks，外部 Query 应该已经将 hasSubLinks 设置为 true，因此这
 * 仅与未展平的子查询相关。
 *
 * 注意：这用于尚未规划的表达式。我们不期望它直接应用于整个 Query，因此如果我们一开始看到
 * 一个 Query，我们确实希望增加 sublevels_up（这在 LATERAL 子查询中发生）。
 */
Node * flatten_join_alias_vars(Query *fc_query, Node *fc_node)
{
	flatten_join_alias_vars_context fc_context;

	fc_context.query = fc_query;
	fc_context.sublevels_up = 0;
	/* 标记连接别名是否可能包含 SubLinks */
	fc_context.possible_sublink = fc_query->hasSubLinks;
	/* 如果hasSubLinks已经为真，则无需费力 */
	fc_context.inserted_sublink = fc_query->hasSubLinks;

	return fc_flatten_join_alias_vars_mutator(fc_node, &fc_context);
}

static Node * fc_flatten_join_alias_vars_mutator(Node *fc_node,
								flatten_join_alias_vars_context *fc_context)
{
	if (fc_node == NULL)
		return NULL;
	if (IsA(fc_node, Var))
	{
		Var		   *fc_var = (Var *) fc_node;
		RangeTblEntry *fc_rte;
		Node	   *fc_newvar;

		/* 除非 Var 属于目标级别的 JOIN，否则不做更改 */
		if (fc_var->varlevelsup != fc_context->sublevels_up)
			return fc_node;		/* 实际上不需要复制 */
		fc_rte = rt_fetch(fc_var->varno, fc_context->query->rtable);
		if (fc_rte->rtekind != RTE_JOIN)
			return fc_node;
		if (fc_var->varattno == InvalidAttrNumber)
		{
			/* 必须扩展整个行引用 */
			RowExpr    *fc_rowexpr;
			List	   *fc_fields = NIL;
			List	   *fc_colnames = NIL;
			ListCell   *fc_lv;
			ListCell   *fc_ln;

			Assert(list_length(fc_rte->joinaliasvars) == list_length(fc_rte->eref->colnames));
			forboth(fc_lv, fc_rte->joinaliasvars, fc_ln, fc_rte->eref->colnames)
			{
				fc_newvar = (Node *) lfirst(fc_lv);
				/* 忽略已删除的列 */
				if (fc_newvar == NULL)
					continue;
				fc_newvar = copyObject(fc_newvar);

				/*
				 * 如果我们正在扩展从上层查询传下来的别名，必须调整其 varlevelsup 字段。
				 */
				if (fc_context->sublevels_up != 0)
					IncrementVarSublevelsUp(fc_newvar, fc_context->sublevels_up, 0);
				/* 如果可能，保留原始 Var 的位置 */
				if (IsA(fc_newvar, Var))
					((Var *) fc_newvar)->location = fc_var->location;
				/* 递归以防连接输入本身是一个连接 */
				/* （如果需要，也会处理设置 inserted_sublink） */
				fc_newvar = fc_flatten_join_alias_vars_mutator(fc_newvar, fc_context);
				fc_fields = lappend(fc_fields, fc_newvar);
				/* 我们也需要未删除列的名称 */
				fc_colnames = lappend(fc_colnames, copyObject((Node *) lfirst(fc_ln)));
			}
			fc_rowexpr = makeNode(RowExpr);
			fc_rowexpr->args = fc_fields;
			fc_rowexpr->row_typeid = fc_var->vartype;
			fc_rowexpr->row_format = COERCE_IMPLICIT_CAST;
			/* vartype 将始终是 RECORDOID，因此我们始终需要 colnames */
			fc_rowexpr->colnames = fc_colnames;
			fc_rowexpr->location = fc_var->location;

			return (Node *) fc_rowexpr;
		}

		/* 扩展连接别名引用 */
		Assert(fc_var->varattno > 0);
		fc_newvar = (Node *) list_nth(fc_rte->joinaliasvars, fc_var->varattno - 1);
		Assert(fc_newvar != NULL);
		fc_newvar = copyObject(fc_newvar);

		/*
		 * 如果我们正在扩展从上层查询传下来的别名，必须
		 * 调整其 varlevelsup 字段。
		 */
		if (fc_context->sublevels_up != 0)
			IncrementVarSublevelsUp(fc_newvar, fc_context->sublevels_up, 0);

		/* 如果可能，保留原始 Var 的位置 */
		if (IsA(fc_newvar, Var))
			((Var *) fc_newvar)->location = fc_var->location;

		/* 递归以防连接输入本身是一个连接 */
		fc_newvar = fc_flatten_join_alias_vars_mutator(fc_newvar, fc_context);

		/* 检测我们是否正在向查询添加子链接 */
		if (fc_context->possible_sublink && !fc_context->inserted_sublink)
			fc_context->inserted_sublink = checkExprHasSubLink(fc_newvar);

		return fc_newvar;
	}
	if (IsA(fc_node, PlaceHolderVar))
	{
		/* 复制 PlaceHolderVar 节点并正确修改子节点 */
		PlaceHolderVar *fc_phv;

		fc_phv = (PlaceHolderVar *) expression_tree_mutator(fc_node,
														 fc_flatten_join_alias_vars_mutator,
														 (void *) fc_context);
		/* 现在修复 PlaceHolderVar 的 relid 集 */
		if (fc_phv->phlevelsup == fc_context->sublevels_up)
		{
			fc_phv->phrels = fc_alias_relid_set(fc_context->query,
										  fc_phv->phrels);
		}
		return (Node *) fc_phv;
	}

	if (IsA(fc_node, Query))
	{
		/* 递归进入RTE子查询或尚未规划的子链接子查询 */
		Query	   *fc_newnode;
		bool		fc_save_inserted_sublink;

		fc_context->sublevels_up++;
		fc_save_inserted_sublink = fc_context->inserted_sublink;
		fc_context->inserted_sublink = ((Query *) fc_node)->hasSubLinks;
		fc_newnode = query_tree_mutator((Query *) fc_node,
									 fc_flatten_join_alias_vars_mutator,
									 (void *) fc_context,
									 QTW_IGNORE_JOINALIASES);
		fc_newnode->hasSubLinks |= fc_context->inserted_sublink;
		fc_context->inserted_sublink = fc_save_inserted_sublink;
		fc_context->sublevels_up--;
		return (Node *) fc_newnode;
	}
	/* 不支持已规划的树 */
	Assert(!IsA(fc_node, SubPlan));
	/* 不应该在这里处理这些规划辅助节点 */
	Assert(!IsA(fc_node, SpecialJoinInfo));
	Assert(!IsA(fc_node, PlaceHolderInfo));
	Assert(!IsA(fc_node, MinMaxAggInfo));

	return expression_tree_mutator(fc_node, fc_flatten_join_alias_vars_mutator,
								   (void *) fc_context);
}

/*
 * alias_relid_set: 在一组 RT 索引中，通过其基础 relids 替换连接
 */
static Relids fc_alias_relid_set(Query *fc_query, Relids fc_relids)
{
	Relids		fc_result = NULL;
	int			fc_rtindex;

	fc_rtindex = -1;
	while ((fc_rtindex = bms_next_member(fc_relids, fc_rtindex)) >= 0)
	{
		RangeTblEntry *fc_rte = rt_fetch(fc_rtindex, fc_query->rtable);

		if (fc_rte->rtekind == RTE_JOIN)
			fc_result = bms_join(fc_result, get_relids_for_join(fc_query, fc_rtindex));
		else
			fc_result = bms_add_member(fc_result, fc_rtindex);
	}
	return fc_result;
}
